package edu.cmu.cs.webapp.ioms.views;

import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;

import edu.cmu.cs.webapp.ioms.dao.DataAccessException;
import edu.cmu.cs.webapp.ioms.dao.impl.FormulaDAOImpl;
import edu.cmu.cs.webapp.ioms.dao.impl.IngredientDAOImpl;
import edu.cmu.cs.webapp.ioms.logging.Alerts;
import edu.cmu.cs.webapp.ioms.models.FormularRecord;
import edu.cmu.cs.webapp.ioms.models.Ingredient;
import edu.cmu.cs.webapp.ioms.models.Product;
import edu.cmu.cs.webapp.ioms.ui.providers.product.IngListViewContentProvider;
import edu.cmu.cs.webapp.ioms.ui.providers.product.IngreLstTblViewerLableProvider;
import edu.cmu.cs.webapp.ioms.utils.IOMSUtils;

public class IngredientListView extends ViewPart implements ISelectionProvider {

	public static final String ID_VIEW = "edu.cmu.cs.webapp.ioms.views.ingredientList";
	// must be changed back to the private in the future
	public TableViewer _viewer;
	private Table _table;
	public Product pro_Changed;

	private ISelectionChangedListener listener;

	// set the format of the displaying data
	private IngreLstTblViewerLableProvider labelProvider;

	// need to changed to ingredient
	/*
	 * private PurchaseOrder[] orders;
	 */
	private FormularRecord[] records;

	@Override
	public void init(IViewSite site) throws PartInitException {
		super.init(site);
		site.setSelectionProvider(this);

		// register the listener to the ProductView, using site to specify the
		// current workbench

		ProductView.getProductsListViewPart(site).addSelectionChangedListener(
				listener);

	}

	public IngredientListView() {
		labelProvider = new IngreLstTblViewerLableProvider();
		listener = new ISelectionChangedListener() {

			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				// event.getSelection();

				ISelection selection = event.getSelection();
				if (selection instanceof IStructuredSelection) {

					Object obj = ((IStructuredSelection) selection)
							.getFirstElement();

					if (obj instanceof Product) {
						pro_Changed = (Product) obj;
						// use the DAO to get another content provider, either
						// set input or set the content provider
						try {
							List<FormularRecord> list = new FormulaDAOImpl()
									.getFormProd(pro_Changed);
							FormularRecord[] rList = new FormularRecord[list
									.size()];
							int count = 0;
							for (FormularRecord fr : list) {
								if (fr != null) {
									rList[count] = fr;
									count++;
								}
							}

							_viewer.setInput(rList);

						} catch (DataAccessException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}

					}
					// should change the refIngListView to update the display
					refIngrListView();
				}

			}
		};
	}

	private void createTableViewer(Composite parent) {

		GridData gridData = new GridData();
		gridData.horizontalSpan = 5;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = SWT.FILL;
		gridData.verticalAlignment = SWT.FILL;

		_table = new Table(parent, SWT.FULL_SELECTION | SWT.BORDER
				| SWT.H_SCROLL | SWT.V_SCROLL);
		_table.setLayoutData(gridData);
		_table.setHeaderVisible(true);
		_table.setLinesVisible(true);

		TableColumn ing_ID = new TableColumn(_table, SWT.NONE);
		ing_ID.setText("#");
		ing_ID.setWidth(60);
		ing_ID.setMoveable(false);
		ing_ID.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				_viewer.setSorter(new IngredientListSorter(
						IngreLstTblViewerLableProvider.INGREDIENT_ID,
						sortDirection == SWT.DOWN));
			}
		});

		// following is your first tiral of adding sorting property into the
		// table

		TableColumn ing_Name = new TableColumn(_table, SWT.NONE);
		ing_Name.setText("Name");
		ing_Name.setWidth(150);
		ing_Name.setMoveable(true);
		ing_ID.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				_viewer.setSorter(new IngredientListSorter(
						IngreLstTblViewerLableProvider.INGREDIENT_ID,
						sortDirection == SWT.DOWN));
			}
		});

		TableColumn ing_Quantity = new TableColumn(_table, SWT.NONE);
		ing_Quantity.setText("Quantity");
		ing_Quantity.setWidth(95);
		ing_Quantity.setMoveable(true);
		ing_Quantity.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				_viewer.setSorter(new IngredientListSorter(
						IngreLstTblViewerLableProvider.INGREDIENT_ID,
						sortDirection == SWT.DOWN));
			}
		});

		TableColumn ing_Price = new TableColumn(_table, SWT.NONE);
		ing_Price.setText("Unit Cost");
		ing_Price.setWidth(95);
		ing_Price.setMoveable(true);
		ing_Price.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				_viewer.setSorter(new IngredientListSorter(
						IngreLstTblViewerLableProvider.INGREDIENT_ID,
						sortDirection == SWT.DOWN));
			}
		});

		/*
		 * TableColumn ing_Remark = new TableColumn(_table, SWT.CENTER);
		 * ing_Remark.setAlignment(SWT.CENTER); ing_Remark.setText("Details");
		 * ing_Remark.setWidth(250); ing_Remark.setMoveable(true);
		 * ing_Remark.addSelectionListener(new SelectionAdapter() { public void
		 * widgetSelected(SelectionEvent e) { int sortDirection = IOMSUtils
		 * .updateSortDirection((TableColumn) e.widget); _viewer.setSorter(new
		 * IngredientListSorter( IngreLstTblViewerLableProvider.INGREDIENT_ID,
		 * sortDirection == SWT.DOWN)); } });
		 */

		_viewer = new TableViewer(_table);
		_viewer.setUseHashlookup(true);

		_viewer.setLabelProvider(labelProvider);
		// _viewer.setContentProvider(new OrdersTableViewerContentProvider());

		// name is not good, actually should be the formula content provider
		_viewer.setContentProvider(new IngListViewContentProvider());

		// following line is necessary to set-up the displaying text
		refIngrListView();

	}

	private class IngredientListSorter extends ViewerSorter {
		private int columnIndex;
		private final boolean ascending;

		public IngredientListSorter(int criteria, boolean ascending) {
			super();
			// specify which coloumn needs to be compared
			this.columnIndex = criteria;
			this.ascending = ascending;
		}

		@SuppressWarnings("unchecked")
		@Override
		public int compare(Viewer viewer, Object e1, Object e2) {
			int result = 0;
			if (e1 instanceof Ingredient && e2 instanceof Ingredient) {
				result = getComparator().compare(
						labelProvider.getColumnText(e1, columnIndex),
						labelProvider.getColumnText(e2, columnIndex));
			}

			if (!ascending) {
				result = result * -1;
			}
			return result;
		}
	}

	public void refIngrListView() {

		// need to changed, refresh the input source, actually

		// this._viewer.setInput(new DummieDataGenerator());
		UIJob refreshJob = new RefreshJob("Refresh");
		refreshJob.setUser(true);
		refreshJob.schedule();
	}

	private class RefreshJob extends UIJob {

		public RefreshJob(String name) {
			super(name);
		}

		@Override
		public IStatus runInUIThread(IProgressMonitor monitor) {
			monitor.beginTask("Refreshing Orders List...",
					IProgressMonitor.UNKNOWN);
			try {
				/*
				 * orders = new OrderDAOImpl().getAllOrder().toArray( new
				 * PurchaseOrder[0]);
				 */

				// the product has not been specified
				if (pro_Changed != null) {
					List<FormularRecord> recordList = new FormulaDAOImpl()
							.getFormProd(pro_Changed);
					records = new FormularRecord[recordList.size()];

					// turn the records in to a array
					int count = 0;
					for (FormularRecord i : recordList) {
						if (i != null) {
							i.setIngredient(new IngredientDAOImpl().getIng(i
									.getIngredient()));
							records[count] = i;
							count++;
						}
					}

				}

			} catch (DataAccessException e) {
				Alerts.getInstance().detailError("Data Access Error",
						e.getLocalizedMessage(), e);
				return Status.CANCEL_STATUS;
			}

			/*
			 * if (orders != null) { _viewer.setInput(orders); }
			 */

			if (records != null) {
				_viewer.setInput(records);
			}
			monitor.done();

			return Status.OK_STATUS;
		}
	}

	@Override
	public void createPartControl(Composite parent) {

		// set the layout for the parent composite
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 5;
		gridLayout.marginBottom = 1;
		gridLayout.marginTop = 1;
		parent.setLayout(gridLayout);

		// the composite is to embedded into the parent composite
		// the second layer
		Composite secLayer = new Composite(parent, SWT.NONE);
		GridData data = new GridData(SWT.NONE);
		data.horizontalAlignment = SWT.FILL;
		data.verticalAlignment = SWT.BEGINNING;
		data.grabExcessHorizontalSpace = true;
		secLayer.setLayoutData(data);

		GridLayout secLayerLayout = new GridLayout();
		secLayerLayout.numColumns = 5;
		secLayer.setLayout(secLayerLayout);

		// create the view for table in the parent composite
		createTableViewer(parent);
	}

	@Override
	public void setFocus() {
		// could set to the first element of the table view
	}

	@Override
	public void addSelectionChangedListener(ISelectionChangedListener listener) {
		this._viewer.addSelectionChangedListener(listener);

	}

	@Override
	public ISelection getSelection() {
		if (_viewer != null)
			return _viewer.getSelection();
		return null;
	}

	@Override
	public void removeSelectionChangedListener(
			ISelectionChangedListener listener) {
		// TODO Auto-generated method stub

	}

	@Override
	public void setSelection(ISelection selection) {
		// TODO Auto-generated method stub

	}

	/**
	 * 
	 * @param site
	 * @return
	 */
	public static IngredientListView getFormulaListViewPart(IViewSite site) {
		IViewPart view = site.getPage().findView(IngredientListView.ID_VIEW);
		if (view instanceof IngredientListView) {
			return ((IngredientListView) view);
		}
		return null;
	}

}
